package com.nofeng.wx.third;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.nofeng.wx.utils.TemplateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

@Service
public class WxGzhApi {


    // 在代码中写死的AppID和AppSecret
    private static final String APP_ID = "wx5948c0e547a72639";
    private static final String APP_SECRET = "1283b792e3ceabfd50f324dd04aa4007";
    private static final int TOKEN_EXPIRE_SECONDS = 70; // Token缓存70秒

    // Token缓存相关变量
    private String cachedToken;
    private long tokenExpireTime;
    private final ScheduledExecutorService tokenCleaner = Executors.newSingleThreadScheduledExecutor();

    private final RestTemplate restTemplate = new RestTemplate();

    public WxGzhApi() {
        // 启动定时任务，每分钟检查一次Token是否过期
        tokenCleaner.scheduleAtFixedRate(this::cleanExpiredToken, 1, 1, TimeUnit.MINUTES);
    }


    // 清理过期Token
    private void cleanExpiredToken() {
        if (isTokenExpired()) {
            cachedToken = null;
        }
    }

    // 检查Token是否过期
    private boolean isTokenExpired() {
        return System.currentTimeMillis() > tokenExpireTime;
    }

    // 获取AccessToken
    private String getAccessToken() {
        // 如果缓存中有未过期的Token，直接返回
        if (cachedToken != null && !isTokenExpired()) {
            return cachedToken;
        }

        // 请求微信API获取Token
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" +
                "&appid=" + APP_ID + "&secret=" + APP_SECRET;

        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
        JSONObject json = JSON.parseObject(response.getBody());
        String token = json.getString("access_token");

        if (token != null) {
            // 缓存Token，设置70秒后过期
            cachedToken = token;
            tokenExpireTime = System.currentTimeMillis() + TOKEN_EXPIRE_SECONDS * 1000L;
            return token;
        }
        throw new RuntimeException("获取Token失败: " + json);
    }

    /**
     * 获取所有素材的media_id列表
     *
     * @return 包含所有素材media_id的列表
     */
    public List<JSONObject> getAllMedia() {
        List<JSONObject> allMediaIds = new ArrayList<>();

        // 获取所有素材类型
        String[] materialTypes = {"image", "video", "voice", "news"};

        for (String type : materialTypes) {
            int offset = 0;
            int count = 20; // 微信API每次最多返回20条

            while (true) {
                JSONObject batchGetResult = batchGetMaterial(type, offset, count);
                if (batchGetResult == null) break;

                JSONArray items = batchGetResult.getJSONArray("item");
                if (items == null || items.isEmpty()) break;

                for (int i = 0; i < items.size(); i++) {
                    JSONObject item = items.getJSONObject(i);
                    String mediaId = item.getString("media_id");
                    if (mediaId != null && !mediaId.isEmpty()) {
                        allMediaIds.add(item);
                    }
                }

                // 检查是否还有更多素材
                int totalCount = batchGetResult.getIntValue("total_count");
                int itemCount = batchGetResult.getIntValue("item_count");

                offset += itemCount;
                if (offset >= totalCount) break;
            }
        }

        return allMediaIds;
    }

    /**
     * 批量获取素材
     *
     * @param type 素材类型：image, video, voice, news
     * @param offset 从全部素材的该偏移位置开始返回
     * @param count 返回素材的数量
     * @return 素材列表结果
     */
    private JSONObject batchGetMaterial(String type, int offset, int count) {
        String token = getAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=" + token;

        // 构建请求体
        JSONObject requestBody = new JSONObject();
        requestBody.put("type", type);
        requestBody.put("offset", offset);
        requestBody.put("count", count);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> request = new HttpEntity<>(requestBody.toJSONString(), headers);

        try {
            ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
            JSONObject result = JSON.parseObject(response.getBody());

            // 检查错误
            if (result.getInteger("errcode") != null && result.getInteger("errcode") != 0) {
                System.out.println(result);
                return null;
            }

            return result;
        } catch (Exception e) {
            if (e.getMessage().contains("40001")) { // Token过期
                cachedToken = null;
                return batchGetMaterial(type, offset, count); // 重试
            }
            throw new RuntimeException("获取素材失败: " + e.getMessage(), e);
        }
    }


    public static class WxGzhDraft  {
        // 文章列表
        private List<WxGzhArticle> articles;

        // 构造方法
        public WxGzhDraft() {}

        public WxGzhDraft(List<WxGzhArticle> articles) {
            this.articles = articles;
        }

        // Getter和Setter方法
        public List<WxGzhArticle> getArticles() { return articles; }
        public void setArticles(List<WxGzhArticle> articles) { this.articles = articles; }

        // 转换为JSON对象
        public JSONObject toJSONObject() {
            JSONObject json = new JSONObject();
            JSONArray articlesArray = new JSONArray();

            for (WxGzhArticle article : articles) {
                JSONObject articleJson = new JSONObject();
                articleJson.put("title", article.getTitle());
                articleJson.put("author", article.getAuthor());
                articleJson.put("content", article.getContent());
                articleJson.put("content_source_url", article.getContentSourceUrl());
                articleJson.put("digest", article.getDigest());
                articleJson.put("thumb_media_id", article.getThumbMediaId());
                articleJson.put("show_cover_pic", article.getShowCoverPic());
                articleJson.put("need_open_comment", article.getNeedOpenComment());
                articleJson.put("only_fans_can_comment", article.getOnlyFansCanComment());

                articlesArray.add(articleJson);
            }

            json.put("articles", articlesArray);
            return json;
        }

        // 从JSON字符串解析
        public static WxGzhDraft fromJSON(String jsonString) {
            JSONObject json = JSONObject.parseObject(jsonString);
            JSONArray articlesArray = json.getJSONArray("articles");

            WxGzhDraft draft = new WxGzhDraft();
            draft.articles = JSONArray.parseArray(articlesArray.toJSONString(), WxGzhArticle.class);

            return draft;
        }

    }
    public static class WxGzhArticle {
        // 标题
        private String title;

        // 作者
        private String author;

        // 正文内容（HTML格式）
        private String content;

        // 原文链接
        @JSONField(name = "content_source_url")
        private String contentSourceUrl;

        // 摘要
        private String digest;

        // 封面图片media_id
        @JSONField(name = "thumb_media_id")
        private String thumbMediaId;

        // 是否显示封面（0不显示，1显示）
        @JSONField(name = "show_cover_pic")
        private int showCoverPic = 1;

        // 是否打开评论（0不打开，1打开）
        @JSONField(name = "need_open_comment")
        private int needOpenComment = 1;

        // 是否粉丝才可评论（0所有人可评论，1粉丝才可评论）
        @JSONField(name = "only_fans_can_comment")
        private int onlyFansCanComment = 1;

        // 构造方法
        public WxGzhArticle() {}

        public WxGzhArticle(String title, String author, String content, String contentSourceUrl,
                       String digest, String thumbMediaId) {
            this.title = title;
            this.author = author;
            this.content = content;
            this.contentSourceUrl = contentSourceUrl;
            this.digest = digest;
            this.thumbMediaId = thumbMediaId;
        }

        // Getter和Setter方法
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }

        public String getAuthor() { return author; }
        public void setAuthor(String author) { this.author = author; }

        public String getContent() { return content; }
        public void setContent(String content) { this.content = content; }

        public String getContentSourceUrl() { return contentSourceUrl; }
        public void setContentSourceUrl(String contentSourceUrl) { this.contentSourceUrl = contentSourceUrl; }

        public String getDigest() { return digest; }
        public void setDigest(String digest) { this.digest = digest; }

        public String getThumbMediaId() { return thumbMediaId; }
        public void setThumbMediaId(String thumbMediaId) { this.thumbMediaId = thumbMediaId; }

        public int getShowCoverPic() { return showCoverPic; }
        public void setShowCoverPic(int showCoverPic) { this.showCoverPic = showCoverPic; }

        public int getNeedOpenComment() { return needOpenComment; }
        public void setNeedOpenComment(int needOpenComment) { this.needOpenComment = needOpenComment; }

        public int getOnlyFansCanComment() { return onlyFansCanComment; }
        public void setOnlyFansCanComment(int onlyFansCanComment) { this.onlyFansCanComment = onlyFansCanComment; }

    }


    // 创建草稿
    public String createDraft(WxGzhArticle article) {
        String token = getAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/draft/add?access_token=" + token;

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 创建草稿对象
        WxGzhDraft draft = new WxGzhDraft(Lists.newArrayList(article));
        String jsonString = draft.toJSONObject().toJSONString();
        HttpEntity<String> request = new HttpEntity<>(jsonString, headers);

        try {
            ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
            return handleResponse(response.getBody());
        } catch (Exception e) {
            return handleTokenExpired( draft, e);
        }
    }

    // 创建草稿
    public String updateDraft(String mediaId,WxGzhArticle article) {
        String token = getAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/draft/update?access_token=" + token;
        /**
         * {
         *   "mediaId": "你的草稿media_id",
         *   "index": 0,
         *   "article": {
         *     "title": "更新后的文章标题",
         *     "author": "新的作者名"
         *   }
         * }
         */

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 创建草稿对象
        Map<String,Object> update= Maps.newHashMap();
        update.put("mediaId",mediaId);
        update.put("index",0);
        update.put("article",article);

        String jsonString = JSON.toJSONString(update);
        HttpEntity<String> request = new HttpEntity<>(jsonString, headers);

        try {
            ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
            return handleResponse(response.getBody());
        } catch (Exception e) {
            e.printStackTrace();
            return "{}";
        }
    }


    // 处理Token过期
    private String handleTokenExpired(WxGzhDraft draft , Exception e) {
        if (e.getMessage().contains("40001")) { // 微信Token过期错误码
            cachedToken = null; // 清除缓存
            return createDraft(draft.getArticles().get(0)); // 重试
        }
        throw new RuntimeException("创建草稿失败", e);
    }

    // 处理微信API响应
    private String handleResponse(String responseBody) {
        JSONObject json = JSON.parseObject(responseBody);
        if (json.getInteger("errcode") != null && json.getInteger("errcode") != 0) {
            throw new RuntimeException("微信API错误: " + json);
        }
        return responseBody;
    }

    // 应用关闭时清理资源
    public void destroy() {
        tokenCleaner.shutdown();
    }
}